package models

import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"time"
)

type TimeField struct {
	CreatedAt Datetime `json:"created_at"`
	UpdatedAt Datetime `json:"updated_at"`
}
type DeleteField struct {
	DeletedAt Datetime `json:"deleted_at"`
}
type BaseModel struct {
	ID uint `gorm:"primary_key" json:"id"`
	TimeField
}

const TimeFormat = "2006-01-02 15:04:05"

type Datetime time.Time

func (this *Datetime) UnmarshalJSON(data []byte) (err error) {
	now, err := time.ParseInLocation(`"`+TimeFormat+`"`, string(data), time.Local)
	*this = Datetime(now)
	return
}

func (this Datetime) MarshalJSON() ([]byte, error) {
	tt := time.Time(this)
	if tt.IsZero() {
		emptyStr, _ := json.Marshal("")
		return emptyStr, nil
	}
	b := make([]byte, 0, len(TimeFormat)+2)
	b = append(b, '"')
	b = tt.AppendFormat(b, TimeFormat)
	b = append(b, '"')
	return b, nil
}

func (this Datetime) Value() (driver.Value, error) {
	var zeroTime time.Time
	tt := time.Time(this)
	if tt.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return tt, nil
}

func (this *Datetime) Scan(v interface{}) error {
	value, ok := v.(time.Time)
	if ok {
		*this = Datetime(value)
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}

func (this Datetime) IsZero() bool {
	tt := time.Time(this)
	if tt.IsZero() {
		return true
	}
	return false
}

func (this Datetime) String() string {
	tt := time.Time(this)
	return tt.String()
}

func (this Datetime) Format() string {
	tt := time.Time(this)
	return tt.Format(TimeFormat)
}

func (this Datetime) After(t Datetime) bool {
	tt := time.Time(this)
	return tt.After(time.Time(t))
}

func (this Datetime) Before(t Datetime) bool {
	tt := time.Time(this)
	return tt.Before(time.Time(t))
}

func (this Datetime) Parse(t string) (Datetime, error) {
	tt, err := time.Parse(TimeFormat, t)
	return Datetime(tt), err
}
